package wei.xinya.export;

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ExportExcel {
    public static String staticDownloadFilePath = "C:\\Users\\wxy\\Desktop\\datamanager\\";

    public static void main(String[] args) {
        List<String> testData = new ArrayList<>();
        for (int i = 0; i < 500000; i++) {
            testData.add(String.valueOf(i));
        }

        String resultFile = exportCarExcel(testData, "test");
        System.out.println(resultFile);
    }

    /**
     * 生成数据的Excel表文件
     *
     * @param list 数据的集合
     */
    public static String exportCarExcel(List<String> list, String fileName) {
        String fileBaseName = fileName.replace(".csv", "");

        int pageSize = 50000;
        int size = list.size();
        if (size <= pageSize) {
            fileName = fileBaseName + ".xls";
            writeFile(list, fileName);
        } else {
            fileName = fileBaseName + ".zip";
            Map<String, File> zipEntryMap = new HashMap<>();

            List<List<String>> lists = splitList(list, pageSize);
            for (int j = 0; j < lists.size(); j++) {
                List<String> temp = lists.get(j);
                String tempName = fileBaseName + "_" + j + ".xls";
                File writtenFile = writeFile(temp, tempName);
                if (writtenFile == null) {
                    continue;
                }

                zipEntryMap.put(tempName, writtenFile);
            }

            try {
                File zipFile = new File(staticDownloadFilePath + fileName);
                ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(zipFile.toPath()));

                for (Map.Entry<String, File> entry : zipEntryMap.entrySet()) {
                    ZipEntry zipEntry = new ZipEntry(entry.getKey());
                    zos.putNextEntry(zipEntry);
                    zos.write(Files.readAllBytes(entry.getValue().toPath()));
                }

                zos.flush();
                zos.closeEntry();
                zos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return fileName;
    }

    private static File writeFile(List<String> list, String fileName) {
        File elsFile;

        try {
            elsFile = new File(staticDownloadFilePath + fileName);
            if (!elsFile.exists()) {
                if (elsFile.createNewFile()) {
                    System.out.println(elsFile + " 创建成功");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        HSSFWorkbook workbook;
        try (FileOutputStream fos = new FileOutputStream(elsFile)) {
            workbook = new HSSFWorkbook();
            // 画图的顶级管理器，一个sheet只能获取一个（一定要注意这点）
            HSSFCellStyle style = workbook.createCellStyle();
            // 设置文字居中
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);

            // 装填数据
            writeSheet(list, workbook, style);
            // 写入文件
            workbook.write(fos);
            workbook.close();
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return elsFile;
    }


    /**
     * 重写writeSheet方法
     * 把数据写入每个表格中
     *
     * @param list     数据集合
     * @param workbook 工作簿对象
     * @param style    工作簿的单元样式
     */
    private static void writeSheet(List<String> list, HSSFWorkbook workbook, CellStyle style) throws IOException {
        HSSFSheet sheet = workbook.createSheet("导出数据");
        int num = 0;

        for (String data : list) {
            Row row = sheet.createRow(num++);
            row.setRowStyle(style);
            row.setHeight((short) 3000);

            createRowAndCell(data, row, 0, style);
        }
    }

    /**
     * 根据当前row行，来创建index标记的列数,并赋值数据
     */
    public static void createRowAndCell(Object obj, Row row, int index, CellStyle style) {
        Cell cell = row.getCell(index);
        if (cell == null) {
            cell = row.createCell(index);
        }

        if (obj != null) {
            cell.setCellValue(obj.toString());
        } else {
            cell.setCellValue("");
        }
        cell.setCellStyle(style);
    }

    /**
     * 拆分列表
     */
    public static <T> List<List<T>> splitList(List<T> list, int interval) {
        if (list != null) {
            int size = list.size();
            if (size > 0) {
                List<List<T>> result = new ArrayList<>();
                if (size <= interval) {
                    result.add(list);
                } else {
                    int remain = size % interval;
                    int frequency = remain == 0 ? size / interval : size / interval + 1;
                    int start = 0;
                    for (int i = 0; i < frequency; i++) {
                        int startIndex = start + i * interval;
                        int endIndex;
                        if (i == frequency - 1) {//最后一次计算特殊，需处理时间边界
                            endIndex = startIndex + (size - i * interval);
                        } else {
                            endIndex = startIndex + interval;
                        }
                        result.add(list.subList(startIndex, endIndex));
                    }
                }
                return result;
            }
        }
        return Collections.emptyList();
    }

}

